/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package org.atomojo.www.util;

import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TreeMap;
import java.util.logging.Logger;
import org.atomojo.app.client.Link;
import org.atomojo.app.client.LinkSet;
import org.restlet.Client;
import org.restlet.Context;
import org.restlet.Request;
import org.restlet.Response;
import org.restlet.data.ChallengeResponse;
import org.restlet.data.ChallengeScheme;
import org.restlet.data.MediaType;
import org.restlet.data.Method;
import org.restlet.data.Protocol;
import org.restlet.data.Reference;
import org.restlet.representation.StringRepresentation;

/**
 *
 * @author alex
 */
public class ResourceManager {

   public static String ATTR = ResourceManager.class.getName();
   
   public class Retriever {
      Entry entry;
      Retriever(Entry entry) {
         this.entry = entry;
      }
      
      public Response get() {
         if (entry.client==null) {
            return null;
         }
         entry.client.getContext().getAttributes().put("hostnameVerifier", org.apache.commons.ssl.HostnameVerifier.DEFAULT);

         log.info("Sending query: "+entry.query+"\nto: "+entry.resource);
         Request remoteRequest = new Request(Method.POST,entry.resource);
         if (entry.link.getUsername()!=null) {
            remoteRequest.setChallengeResponse(new ChallengeResponse(ChallengeScheme.HTTP_BASIC,entry.link.getUsername(),entry.link.getPassword()));
         }
         remoteRequest.setEntity(new StringRepresentation(entry.query,entry.mediaType));
         return entry.client.handle(remoteRequest);
      }
   }
   
   public class Entry {
      Date edited;
      String id;
      String name;
      String path;
      String relation;
      MediaType mediaType;
      String query;
      Client client;
      Reference resource;
      Link link;
      Entry(String id,Date edited,String name,String path,String relation, MediaType mediaType,String query) {
         this.id = id;
         this.edited = edited;
         this.name = name;
         this.path = path;
         this.relation = relation;
         this.mediaType = mediaType;
         this.query = query;
         List<Link> links = linkSet.get(relation);
         if (links!=null && links.size()>0) {
            link = links.get(0);
            client = new Client(new Context(log),Protocol.valueOf(link.getLink().getScheme()));
            resource = new Reference(link.getLink().toString());
         } else {
            link = null;
            resource = null;
            client = null;
         }
      }
      
      public String getId() {
         return id;
      }
      public Date getEdited() {
         return edited;
      }
   }

   Logger log;
   LinkSet linkSet;
   Map<String,Entry> resources;
   Map<String,Entry> byName;
   
   public ResourceManager(Logger log,LinkSet links) {
      this.log = log;
      this.linkSet = links;
      this.resources = new TreeMap<String,Entry>();
      this.byName = new TreeMap<String,Entry>();
   }
   
   public Retriever findResource(String name) {
      Entry entry = byName.get(name);
      return entry!=null ? new Retriever(entry) : null;
   }
   
   public Entry get(String id)
   {
      return resources.get(id);
   }
   
   public void reload(String id,Date edited,String name,String path,String relation,MediaType mediaType,String query) {
      Entry entry = get(id);
      if (entry!=null) {
         entry.edited = edited;
         byName.remove(entry.name);
         entry.name = name;
         byName.put(entry.name,entry);
         entry.path = path;
         entry.relation = relation;
         entry.mediaType = mediaType;
         entry.query = query;
         List<Link> links = linkSet.get(relation);
         if (links!=null && links.size()>0) {
            entry.link = links.get(0);
            entry.client = new Client(new Context(log),Protocol.valueOf(entry.link.getLink().getScheme()));
            entry.resource = new Reference(entry.link.getLink().toString());            
         } else {
            entry.link = null;
            entry.resource = null;
            entry.client = null;
         }
      }
   }
   
   public void add(String id,Date edited,String name,String path,String relation,MediaType mediaType,String query) {
      Entry entry = new Entry(id,edited,name,path,relation,mediaType,query);
      resources.put(id,entry);
      log.info("Resource: "+name+" -> "+id);
      byName.put(name, entry);
   }
   
   public void remove(String id) {
      Entry entry = resources.remove(id);
      if (entry!=null) {
         byName.remove(entry.name);
      }
   }
   
   public Set<String> getKeys() {
      return resources.keySet();
   }
}
